﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using FishServe.Client.Application.Manifest;
using System.Reflection;
using System.IO;

namespace FishServe.Client.Application
{
    internal class ModuleLoader
    {
        private string _applicationDir;
        private Dictionary<string, Assembly> _loadedModules = new Dictionary<string,Assembly>();

        internal ModuleLoader(string applicationDir)
        {
            _applicationDir = applicationDir;
        }

        internal Assembly LoadModule(ManifestModuleTypeInfo moduleManifestTypeInfo)
        {
            return LoadModule(moduleManifestTypeInfo.Module.Name, moduleManifestTypeInfo.Module.Version.ToString());
        }

        internal Assembly LoadModule(ModuleManifest moduleManifest)
        {
            return LoadModule(moduleManifest.Module.Name, moduleManifest.Module.Version.ToString());
        }

        private Assembly LoadModule( string moduleName, string moduleVersion )
        {
            Assembly assembly=null;
            string moduleNameVersion = moduleName + "." + moduleVersion;

            if (!_loadedModules.TryGetValue(moduleNameVersion, out assembly))
            {
                string modulefilename = Path.Combine(Path.Combine(Path.Combine( Path.Combine(_applicationDir, "Modules"), moduleName), moduleVersion), moduleName + ".dll");
                if (!File.Exists(modulefilename))
                    throw new FileNotFoundException(String.Format("ModuleLoader: cannot find module '{0}'", modulefilename));
                try
                {
                    assembly = Assembly.LoadFrom(modulefilename);
                    if (assembly != null)
                        _loadedModules.Add(moduleNameVersion, assembly);
                }
                catch (Exception ex)
                {
                    throw new Exception(String.Format("ModuleLoader failed to load module '{0}'", modulefilename), ex);
                }
            }

            return assembly;

        }
    }
}
